﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Web;
using SocialLearning.CoreInterfaces;
using SocialLearning;

namespace ArchitectureV2
{
    public class UserSession
    {
        #region Constants

        const int TimeoutMinutes = 5;

        #endregion

        #region Fields

        private string username, password;
        private I_UAC_Account user;
        private Core core;
        private Dictionary<string, UserModule> userModules;
        private DateTime lastUsed;

        #endregion

        #region Constructor

        public UserSession(I_UAC_Account user, ModuleLoader modules,
            string username, string password)
        {
            this.user = user;
            this.username = username;
            this.password = password;
            core = new Core(this);
            userModules = modules.LoadModules(core);
            lastUsed = DateTime.Now;
        }

        ~UserSession() { Logout(); }

        #endregion

        #region Properties

        public I_UAC_Account User { get { return (user); } }
        public bool IsExpired { get { return ((DateTime.Now - lastUsed).TotalMinutes >= TimeoutMinutes); } }

        #endregion

        #region Public Methods

        public void Logout()
        {
            lastUsed = DateTime.Now;
            if (user != null) { SetClientPingEndpoint(null, 0); }
            ModuleLoader.UnloadModules(userModules);
            user = null; userModules = null;
        }

        public bool IsLoggedIn()
        {
            lastUsed = DateTime.Now;
            return (user != null);
        }

        public int GetUserID()
        {
            try
            {
                return ((int)InvokeMethod("Login", "LoginUser", new object[] { username, password }));
            }
            catch { return (-99); }
        }

        public string[] GetModuleList()
        {
            lastUsed = DateTime.Now;
            if (user == null) { throw new Exception("Not logged in!"); }
            return (userModules.Keys.ToArray());
        }

        public string[] GetMethodList(string module)
        {
            UserModule mod; lastUsed = DateTime.Now;
            if (user == null) { throw new Exception("Not logged in!"); }
            if (userModules.TryGetValue(module, out mod) == false) { return (null); }
            return (mod.MethodList);
        }

        public UAC_Account GetSomeUser(string username)
        {
            UAC_Account user = (new UAC_UserManagement()).Search(username);
            return (user);
        }

        public void SetClientPingEndpoint(string ip, int port)
        {
            lastUsed = DateTime.Now;
            if (user == null) { throw new Exception("Not logged in!"); }
            if (ip == null) { core.Deregister(user); }
            else
            {
                IPAddress addr;
                if (IPAddress.TryParse(ip, out addr) == false) { return; }
                core.Register(user, new IPEndPoint(addr, port));
            }
        }

        public object InvokeMethod(string module, string method, object[] parameters)
        {
            UserModule mod; lastUsed = DateTime.Now;
            if (user == null) { throw new Exception("Not logged in!"); }
            if (userModules.TryGetValue(module, out mod) == false)
            {
                throw new Exception(String.Format("Module {0} not found!", module));
            }
            return (mod.InvokeMethod(method, parameters));
        }

        #endregion

        #region Debug Methods

        public int GetActivePingedUsers()
        {
            lastUsed = DateTime.Now;
            return (core.UserCount);
        }

        #endregion
    }
}